/**
 * Node<T>:
 *     Node of a Search Heap of type T.
 * 
 * Designed and written by Jonathan E. Landrum.
 * 
 * Copyright (c) 2014-2015 Jonathan E. Landrum. All Rights Reserved.
 */
public class Node<T> {
    // T objects stored in this Node
    private T[] arr = new T[4];
    private int numElements;
    
    // Pointers to children of this Node
    private Node<T> parent = null;
    private Node<T> leftSibling = null;
    private Node<T> rightSibling = null;
    private Node<T> leftChild = null;
    private Node<T> rightChild = null;
    
    /*
     * Constructors
     */
    public Node() { numElements = 0; }
    public Node(T minimum) {
        min = minimum;
        numElements = 1;
    }
    public Node(T minimum, T maximum) {
        min = minimum;
        max = maximum;
        numElements = 2;
    }
    public Node(T minimum, T median, T maximum) {
        min = minimum;
        med = median;
        max = maximum;
        numElements = 3;
    }
    
    /*
     * Getters
     */
    public T getMin() { return min; }
    public T getMed() { return med; }
    public T getMax() { return max; }
    public Node<T> getParent() { return parent; }
    public Node<T> getLeftSibling() { return leftSibling; }
    public Node<T> getRightSibling() { return rightSibling; }
    public Node<T> getLeftChild() { return leftChild; }
    public Node<T> getRightChild() { return rightChild; }
    public int getNumElements() { return numElements; }
    
    /*
     * Setters
     */
    public void setParent(Node<T> obj) { parent = obj; }
    public void setLeftSibling(Node<T> obj) { leftSibling = obj; }
    public void setRightSibling(Node<T> obj) { rightSibling = obj; }
    public void setLeftChild(Node<T> obj) { leftChild = obj;  }
    public void setRightChild(Node<T> obj) { rightChild = obj; }
    public void setNumElements(int n) { numElements = n; }
    
    /*
     * Booleans
     */
    public boolean isRoot() { return parent == null; }
    public boolean isFull() {
        return (this.hasMin() && this.hasMed() && this.hasMax());
    }
    public boolean isLeftChild() { return this == parent.getLeftChild(); }
    public boolean isRightChild() { return this == parent.getRightChild(); }
    public boolean hasMin() { return min != null; }
    public boolean hasMed() { return med != null; }
    public boolean hasMax() { return max != null; }
    public boolean hasParent() { return parent != null; }
    public boolean hasLeftSibling() { return leftSibling != null; }
    public boolean hasRightSibling() { return rightSibling != null; }
    public boolean hasLeftChild() { return leftChild != null; }
    public boolean hasRightChild() { return rightChild != null; }
    
    // /*
    //  * Comparable
    //  */
    // public int compareTo(Node<T> node) {
    //     return this.getMax().compareTo(node.getMin());
    // }
    
    /*
     * toString
     */
    public String toString() {
        String res = "";
        if (this.hasMin()) {
            res += "(" + this.getMin();
            if (this.hasMed()) {
                res += ", " + this.getMed();
            }
            if (this.hasMax()) {
                res += ", " + this.getMax();
            }
            res += ")";
        }
        return res;
    }
}
